/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package co.edu.unal.bioingenium.kbmed.text.representation.vo;

import co.edu.unal.bioingenium.kbmed.util.data.QuickSort;
import gnu.trove.map.TObjectIntMap;
import gnu.trove.map.hash.TObjectIntHashMap;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 *
 * @author lariverosc
 */
public class WordList implements Serializable {

    //SerialUID
    private static final long serialVersionUID = -6403286732224340047L;
    //The word list name
    private String name;
    //The word list for a corpus
    private Set<String> wordList;
    //Alphabetically sorted word list
    private List<String> sortedWordList;
    //The total ocurrences of a word
    private TObjectIntMap<String> wordListTotalOcurrences;
    //The number of documents in wich a word appear
    private TObjectIntMap<String> wordListInObjectOcurrences;
    //Details about the word list construction
    private String constructionDetails;

    /**
     * @param:
     * @return:
     * @param name 
     */
    public WordList(String name) {
        this.name = name;
        wordList = new HashSet<String>();
        wordListTotalOcurrences = new TObjectIntHashMap<String>();
        wordListInObjectOcurrences = new TObjectIntHashMap<String>();
    }

    /**
     * @param:
     * @return:
     * @return 
     */
    public String getName() {
        return name;
    }

    /**
     * @param:
     * @return:
     * @param name 
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * Add a word, to the total occurrences list, if the word exist in the list an occurrence is added, else the word is
     * created and the count is initialized in 1.
     * @param:
     * @return:
     * @param word 
     */
    public void addGlobalOcurrence(String word) {
        if (wordListTotalOcurrences.containsKey(word)) {
            wordListTotalOcurrences.increment(word);
        } else {
            wordListTotalOcurrences.put(word, 1);
        }
    }

    /**
     * Add a word, to the in object occurrences list, if the word exist in the list an occurrence is added, else the word is
     * created and the count is initialized in 1.
     * @param:
     * @return:
     * @param word 
     */
    public void addInObjectOccurence(String word) {
        if (wordListInObjectOcurrences.containsKey(word)) {
            wordListInObjectOcurrences.increment(word);
        } else {
            wordListInObjectOcurrences.put(word, 1);
        }
    }

    /**
     *
     * @param:
     * @return 
     * @return:
     * @param key 
     */
    public int getTotalCount(String key) {
        return wordListTotalOcurrences.get(key);
    }

    /**
     *
     * @param:
     * @return 
     * @return:
     * @param key 
     */
    public int getInObjectCount(String key) {
        return wordListInObjectOcurrences.get(key);
    }

    /**
     * @param:
     * @return:
     * @param word 
     */
    public void addWord(String word) {
        wordList.add(word);
    }

    /**
     * @param:
     * @return:
     * @param word 
     */
    public void removeWord(String word) {
        wordList.remove(word);
    }

    /**
     * @param:
     * @return 
     * @return:
     * @param word 
     */
    public boolean containsWord(String word) {
        return wordList.contains(word);
    }

    /**
     * @param:
     * @return:
     * @return 
     */
    public int getNumWords() {
        return wordList.size();
    }

    /**
     * @param:
     * @return:
     * @return 
     */
    public TObjectIntMap<String> getWordListTotalOcurrences() {
        return wordListTotalOcurrences;
    }

    /**
     * @param:
     * @return:
     * @param wordList 
     */
    public void setWordListTotalOcurrences(TObjectIntMap<String> wordList) {
        this.wordListTotalOcurrences = wordList;
    }

    /**
     * @param:
     * @return:
     * @return 
     */
    public TObjectIntMap<String> getWordListInObjectOcurrences() {
        return wordListInObjectOcurrences;
    }

    /**
     * @param:
     * @return:
     * @param wordListInObjectOcurrences 
     */
    public void setWordListInObjectOcurrences(TObjectIntMap<String> wordListInObjectOcurrences) {
        this.wordListInObjectOcurrences = wordListInObjectOcurrences;
    }

    /**
     * @param:
     * @return:
     * @return 
     */
    public Set<String> getWordList() {
        return wordList;
    }

    /**
     * @param:
     * @return:
     * @param wordList 
     */
    public void setWordList(Set<String> wordList) {
        this.wordList = wordList;
    }

    /**
     * Merge the parameter wordList with the actual word list
     * @param:
     * @return:
     * @param wordList 
     */
    public void merge(WordList wordList) {
        //Merging the list
        for (String word : wordList.getWordList()) {
            if (!this.wordList.contains(word)) {
                this.wordList.add(word);
            }
        }
        //Merging the global count
        for (String word : wordList.getWordListTotalOcurrences().keySet()) {
            if (this.wordListTotalOcurrences.containsKey(word)) {
                this.wordListTotalOcurrences.put(word, this.wordListTotalOcurrences.get(word) + wordList.getTotalCount(word));
            } else {
                this.wordListTotalOcurrences.put(word, wordList.getTotalCount(word));
            }
        }
        //Merging the in object count
        for (String word : wordList.getWordListInObjectOcurrences().keySet()) {
            if (this.wordListInObjectOcurrences.containsKey(word)) {
                this.wordListInObjectOcurrences.put(word, this.wordListInObjectOcurrences.get(word) + wordList.getTotalCount(word));
            } else {
                this.wordListInObjectOcurrences.put(word, wordList.getTotalCount(word));
            }
        }
    }

    /**
     * Return a list of alphabetical ordered words.
     * @param:
     * @return:
     * @return 
     */
    public List<String> getSortedWordList() {
        if (sortedWordList != null && sortedWordList.size() == wordList.size()) {
            return sortedWordList;
        } else {
            sortedWordList = new ArrayList<String>();
            for (String word : wordList) {
                sortedWordList.add(word);
            }
            Collections.sort(sortedWordList);
            return sortedWordList;
        }
    }

    /**
     * 
     * @return
     */
    public String getConstructionDetails() {
        return constructionDetails;
    }

    /**
     * 
     * @param constructionDetails
     */
    public void setConstructionDetails(String constructionDetails) {
        this.constructionDetails = constructionDetails;
    }
}
